#include <iostream>
#include <string>
#include <memory>


// 抽象产品类
class Computer
{
public:
    void SetMainboard(const std::string& mainboard) { _mainboard = mainboard; }
    void SetScreen(const std::string& screen) { _screen = screen; }
    virtual void SetOS() = 0;
    void show()
    {
        std::string ret = _mainboard + ":" + _screen + ":" + _os;
        std::cout << ret << std::endl;
    }
protected:
    std::string _mainboard;
    std::string _screen;
    std::string _os;
};

// 具体产品类
class MACBook : public Computer
{
public:
    void SetOS() override { _os = "MAC OS A17"; }
};

// 抽象建造者类
class Builder
{
public:
    virtual void BuildMainboard(const std::string& mainboard) = 0;
    virtual void BuildScreen(const std::string &screen) = 0;
    virtual void BuildOS() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 具体建造者类
class MacBookBuilder : public Builder
{
public:
    MacBookBuilder():_computer(std::make_shared<MACBook>()) {}
    void BuildMainboard(const std::string& mainboard) override { _computer->SetMainboard(mainboard); }
    void BuildScreen(const std::string &screen) override { _computer->SetScreen(screen); }
    void BuildOS() override { _computer->SetOS(); }
    std::shared_ptr<Computer> build() { return _computer; }
private:
    std::shared_ptr<Computer> _computer;
};


// 指挥者类
class Director
{
public:
    Director(std::unique_ptr<Builder> builder) :_builder(std::move(builder)) {}
    void construct(const std::string &mainboard, const std::string &screen)
    {
        _builder->BuildMainboard(mainboard);
        _builder->BuildScreen(screen);
        _builder->BuildOS();
    }
    std::shared_ptr<Computer> GetProduct() { return _builder->build(); }
private:
    std::unique_ptr<Builder> _builder;
};

int main()
{
    // 1.有一个具体产品的建造者
    auto builder = std::make_unique<MacBookBuilder>();

    // 2.有一个指挥者，指挥建造者
    Director director(std::move(builder));
    director.construct("主板", "显示器");

    // 3.获取产品
    auto mac = director.GetProduct();
    mac->show();
    return 0;
}